/***********************************************************************************
 * 文件名： mcu_adc.h
 * 作者： 刘言
 * 版本： 5
 * 说明：
 * 		ADC驱动。
 * 修改记录：
 * 	2020/8/19: 初版。 刘言。
 *  2020/11/7: V2。新增扫描转换功能。单次转换现在不用在意ADC中断状态、是否单次模式，已经内部处理。
 *  2020/12/21: V3。mIsBusy增加volatile修饰，解决编译器优化后不再判断mIsBusy导致死机问题。
 *              跨线程（中断）全局变量同步务必加volatile。
 *  2021/3/20: V4.增加温度传感器开关静态配置项；初始化后ADC默认是否使能；异步转换功能；ADC使能、失能API。
 * 2022/07/15: 支持所有通道扫描；固定使用TIM2定时扫描；内部处理中断。
***********************************************************************************/

#ifndef _MCU_ADC_H_
#define _MCU_ADC_H_

#include "mcu.h"

// 可选的参考电压源
typedef enum _adc_vref_t
{
    ADC_VREF_ON_CHIP_1500,
    ADC_VREF_ON_CHIP_2500,
    ADC_VREF_EXTERNAL,
    ADC_VREF_VDD
}adc_vref_t;

// 用来通知转换结果的回调函数类型
typedef void (*adc_result_callback_t)(u16 result);


// 参数计算
#if (ADC_SREF == 0)
#define ADC_FULL_VOLTAGE    1500
#elif (ADC_SREF == 1)
#define ADC_FULL_VOLTAGE    2500
#else
//#define ADC_FULL_VOLTAGE    5000  // 自己定义
#endif

#if (HC32_MCU_SERIES == HC32F005)
    #define _ADC_CH_VDD_3      9       // 内部VDD/3通道
    #define _ADC_CH_V12        11      // 内部1.2V电压通道
#else
    #define _ADC_CH_VDD_3      27      // 内部VDD/3通道
    #define _ADC_CH_V12        29      // 内部1.2V电压通道
#endif



//APIs

#define ADC_FULL_VALUE  4095
#define ADC_CH_VREF     _ADC_CH_V12

// ADC初始化，注意没有开启时钟门控，ADC默认是否使能取决于配置文件
// ADC中断入口函数已经被ADC驱动实现，使用者不要再重复定义。
void Adc_Init();

#if (defined ADC_USE_SCAN)
// [异步]开始一次扫描转换，完成后会回调对应通道的函数进行通知（在配置文件中配置）。目前仅支持005。
// 注意：需要先把对应通道的IO口设置为模拟信号模式。将等待其它异步转换任务执行完毕。
void Adc_StartScan();
#endif

#if ((defined ADC_USE_SCAN) && (defined ADC_USE_TIMING_SCAN))
// 开始定时扫描，将会定时启动扫描转换，定时间隔时间取决于 Tim2 配置
// 定时扫描会被 [同步]或者[异步]转换任务暂时打断
#define Adc_StartTimingScan()   Tim2_Run()
// 停止定时扫描
#define Adc_StopTimingScan()    Tim2_Stop()
#endif

// [同步]立即转换并获取一次转换结果
// 注意：需要先把对应通道的IO口设置为模拟信号模式
// 将会等待ADC不繁忙时（完成了异步转换任务）返回
u16 Adc_GetOnce(u8 ch);

// [同步]获取一次有效的（中值滤波）AD值
// 注意：需要先把对应通道的IO口设置为模拟信号模式
// 将首先等待异步转换任务执行完毕。
u16 Adc_GetValue(u8 ch);

// [同步]获取VDD电压，单位mV
// 将首先等待异步转换任务执行完毕。
u16 Adc_GetVDDVoltage();

// [异步]开始一次转换，完成后会通过调用 result_callback 通知转换完成和传递结果
// 将会等待ADC不繁忙时（完成了其它异步转换任务）返回
void Adc_StartOnce(u8 ch, adc_result_callback_t result_callback);

// 关闭ADC
// 同时关闭了BGR、温度传感器
// 注意，ADC关闭状态下开始转换可能会把程序锁死
STATIC_FORCE_IN_LINE void Adc_Disable()
{
#if (HC32_MCU_SERIES == HC32F005)
    M0P_ADC->CR0_f.ADCEN = 0;
#else
    M0P_ADC->CR0_f.EN = 0;
#endif
    M0P_BGR->CR = 0x00;
}

// 开启ADC
// 同时开启了BGR，温度传感器还原为初始状态
STATIC_FORCE_IN_LINE void Adc_Enable()
{
#if (HC32_MCU_SERIES == HC32F005)
    M0P_ADC->CR0_f.ADCEN = 1;
#else
    M0P_ADC->CR0_f.EN = 1;
#endif
    M0P_BGR->CR = (ADC_EN_TS << 1)  // 启动内部温度传感器
                | (1 << 0);         // 使能BGR
}

// void Adc_SetVref(adc_vref_t vref);

#endif


